package edu.gatech.cuckoo;

import static org.junit.Assert.*;

import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.Set;

import org.junit.Before;
import org.junit.Test;

public class HashTableTest {

	HashTable<Integer, String> table;

	@Before
	public void setUp() throws Exception {
		table = new HashTable<Integer, String>();
	}

	@Test
	public void testPut() {
		table.put(10, "dale");
		table.put(2, "hailin");
		assertEquals(2,table.size());
		table.put(null, null);
		assertEquals(2,table.size());
		table.put(8, null);
		assertEquals(3, table.size());
	}

	@Test
	public void testRemove() {
		table.put(55, "tom");
		table.put(90, "chan");
		table.put(77, null);
		assertEquals(3, table.size());
		table.remove(55);
		assertEquals(2, table.size());
		// remove a key that's not in the table
		table.remove(89);
		assertEquals(2, table.size());
		// remove null
		table.remove(null);
		assertEquals(2,table.size());
	}

	@Test
	public void testContains() {
		assertEquals(table.size(), 0);
		table.put(55, "yang");
		table.put(33, "kathy");
		assertFalse(table.contains(0));
		assertTrue(table.contains(55));
		assertTrue(table.contains(33));
	}

	
	@Test
	public void testValues() {
		for(int i = 0; i < 5; i++){
			table.put(i, "aa");
		}
		assertEquals(table.size(), 5);

		Collection<String> values = new ArrayList<String>();	
		
		for(int i = 0; i < 5; i++){
			values.add("aa");
		}	
		assertEquals(table.values(), values);
	}

	@Test
	public void testKeySet() {
		for(int i = 0; i < 7; i++){
			table.put(i, "aa");
		}
		assertEquals(table.size(), 7);
		
		Set<Integer> keys = new HashSet<Integer>();
		
		for(int i = 0; i < 7; i++){
			keys.add(i);
		}
		
		assertEquals(table.keySet(), keys);
		
	}

	@Test
	public void testEntrySet() {
		table.put(1, "Dale");
		table.put(2, "Hailin");
		table.put(3, "Trang");
		Set<MapEntry<Integer, String>> entries = new HashSet<MapEntry<Integer, String>>();
		entries.add(new MapEntry<Integer, String>(1, "Dale"));
		entries.add(new MapEntry<Integer, String>(2, "Hailin"));
		entries.add(new MapEntry<Integer, String>(3, "Trang"));
		Set<MapEntry<Integer, String>> tableEntries = table.entrySet();
		for (MapEntry<Integer, String> entry : entries) {
			assertTrue(tableEntries.contains(entry));
			// Don't know why this fails. Verified that both sets have the same entries. - Dale
		}
	}

	@Test
	public void testClear() {
		table.put(22, "Dale");
		table.put(33, "Tina");
		table.put(44, "Snowwhite");
		assertEquals(table.size(), 3);
		table.clear();
		assertEquals(table.size(), 0);
		assertFalse(table.contains(22));
	}

	@Test
	public void testSizeOnEmpty() {
		assertEquals(table.size(), 0);
	}

	@Test
	public void testSizeAfterPut() {
		table.put(22, "Dale");
		assertEquals(table.size(), 1);
		table.put(33, "Tina");
		assertEquals(table.size(), 2);
		table.put(44, "Chuck");
		assertEquals(table.size(), 3);
	}

	@Test
	public void testSizeAfterDuplicate() {
		table.put(22, "Dale");
		assertEquals(table.size(), 1);
		table.put(22, "Dale");
		assertEquals(table.size(), 1);
	}

	@Test
	public void testSizeAfterRemove() {
		table.put(22, "Dale");
		table.put(33, "Tina");
		table.put(44, "Dan");
		assertEquals(table.size(), 3);
		table.remove(44);
		assertEquals(table.size(), 2);
		table.remove(55);
		assertEquals(table.size(), 2);
	}

}
